home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / 5220intf.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  6KB  |  240 lines

  1. /**********************************************************************************************
  2.  
  3.      TMS5220 interface
  4.  
  5.      Written for MAME by Frank Palazzolo
  6.      With help from Neill Corlett
  7.      Additional tweaking by Aaron Giles
  8.  
  9. ***********************************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <math.h>
  14.  
  15. #include "driver.h"
  16. #include "tms5220.h"
  17.  
  18.  
  19. #define MAX_SAMPLE_CHUNK    10000
  20.  
  21. #define FRAC_BITS            14
  22. #define FRAC_ONE            (1 << FRAC_BITS)
  23. #define FRAC_MASK            (FRAC_ONE - 1)
  24.  
  25.  
  26. /* the state of the streamed output */
  27. static const struct TMS5220interface *intf;
  28. static INT16 last_sample, curr_sample;
  29. static UINT32 source_step;
  30. static UINT32 source_pos;
  31. static int stream;
  32.  
  33.  
  34. /* static function prototypes */
  35. static void tms5220_update(int ch, INT16 *buffer, int length);
  36.  
  37.  
  38.  
  39. /**********************************************************************************************
  40.  
  41.      tms5220_sh_start -- allocate buffers and reset the 5220
  42.  
  43. ***********************************************************************************************/
  44.  
  45. int tms5220_sh_start(const struct MachineSound *msound)
  46. {
  47.     intf = msound->sound_interface;
  48.  
  49.     /* reset the 5220 */
  50.     tms5220_reset();
  51.     tms5220_set_irq(intf->irq);
  52.  
  53.     /* set the initial frequency */
  54.     stream = -1;
  55.     tms5220_set_frequency(intf->baseclock);
  56.     source_pos = 0;
  57.     last_sample = curr_sample = 0;
  58.  
  59.     /* initialize a stream */
  60.     stream = stream_init("TMS5220", intf->mixing_level, Machine->sample_rate, 0, tms5220_update);
  61.     if (stream == -1)
  62.         return 1;
  63.  
  64.     /* request a sound channel */
  65.     return 0;
  66. }
  67.  
  68.  
  69.  
  70. /**********************************************************************************************
  71.  
  72.      tms5220_sh_stop -- free buffers
  73.  
  74. ***********************************************************************************************/
  75.  
  76. void tms5220_sh_stop(void)
  77. {
  78. }
  79.  
  80.  
  81.  
  82. /**********************************************************************************************
  83.  
  84.      tms5220_sh_update -- update the sound chip
  85.  
  86. ***********************************************************************************************/
  87.  
  88. void tms5220_sh_update(void)
  89. {
  90. }
  91.  
  92.  
  93.  
  94. /**********************************************************************************************
  95.  
  96.      tms5220_data_w -- write data to the sound chip
  97.  
  98. ***********************************************************************************************/
  99.  
  100. WRITE_HANDLER( tms5220_data_w )
  101. {
  102.     /* bring up to date first */
  103.     stream_update(stream, 0);
  104.     tms5220_data_write(data);
  105. }
  106.  
  107.  
  108.  
  109. /**********************************************************************************************
  110.  
  111.      tms5220_status_r -- read status from the sound chip
  112.  
  113. ***********************************************************************************************/
  114.  
  115. READ_HANDLER( tms5220_status_r )
  116. {
  117.     /* bring up to date first */
  118.     stream_update(stream, 0);
  119.     return tms5220_status_read();
  120. }
  121.  
  122.  
  123.  
  124. /**********************************************************************************************
  125.  
  126.      tms5220_ready_r -- return the not ready status from the sound chip
  127.  
  128. ***********************************************************************************************/
  129.  
  130. int tms5220_ready_r(void)
  131. {
  132.     /* bring up to date first */
  133.     stream_update(stream, 0);
  134.     return tms5220_ready_read();
  135. }
  136.  
  137.  
  138.  
  139. /**********************************************************************************************
  140.  
  141.      tms5220_int_r -- return the int status from the sound chip
  142.  
  143. ***********************************************************************************************/
  144.  
  145. int tms5220_int_r(void)
  146. {
  147.     /* bring up to date first */
  148.     stream_update(stream, 0);
  149.     return tms5220_int_read();
  150. }
  151.  
  152.  
  153.  
  154. /**********************************************************************************************
  155.  
  156.      tms5220_update -- update the sound chip so that it is in sync with CPU execution
  157.  
  158. ***********************************************************************************************/
  159.  
  160. static void tms5220_update(int ch, INT16 *buffer, int length)
  161. {
  162.     INT16 sample_data[MAX_SAMPLE_CHUNK], *curr_data = sample_data;
  163.     INT16 prev = last_sample, curr = curr_sample;
  164.     UINT32 final_pos;
  165.     UINT32 new_samples;
  166.  
  167.     /* finish off the current sample */
  168.     if (source_pos > 0)
  169.     {
  170.         /* interpolate */
  171.         while (length > 0 && source_pos < FRAC_ONE)
  172.         {
  173.             *buffer++ = (((INT32)prev * (FRAC_ONE - source_pos)) + ((INT32)curr * source_pos)) >> FRAC_BITS;
  174.             source_pos += source_step;
  175.             length--;
  176.         }
  177.  
  178.         /* if we're over, continue; otherwise, we're done */
  179.         if (source_pos >= FRAC_ONE)
  180.             source_pos -= FRAC_ONE;
  181.         else
  182.             return;
  183.     }
  184.  
  185.     /* compute how many new samples we need */
  186.     final_pos = source_pos + length * source_step;
  187.     new_samples = (final_pos + FRAC_ONE - 1) >> FRAC_BITS;
  188.     if (new_samples > MAX_SAMPLE_CHUNK)
  189.         new_samples = MAX_SAMPLE_CHUNK;
  190.  
  191.     /* generate them into our buffer */
  192.     tms5220_process(sample_data, new_samples);
  193.     prev = curr;
  194.     curr = *curr_data++;
  195.  
  196.     /* then sample-rate convert with linear interpolation */
  197.     while (length > 0)
  198.     {
  199.         /* interpolate */
  200.         while (length > 0 && source_pos < FRAC_ONE)
  201.         {
  202.             *buffer++ = (((INT32)prev * (FRAC_ONE - source_pos)) + ((INT32)curr * source_pos)) >> FRAC_BITS;
  203.             source_pos += source_step;
  204.             length--;
  205.         }
  206.  
  207.         /* if we're over, grab the next samples */
  208.         if (source_pos >= FRAC_ONE)
  209.         {
  210.             source_pos -= FRAC_ONE;
  211.             prev = curr;
  212.             curr = *curr_data++;
  213.         }
  214.     }
  215.  
  216.     /* remember the last samples */
  217.     last_sample = prev;
  218.     curr_sample = curr;
  219. }
  220.  
  221.  
  222.  
  223. /**********************************************************************************************
  224.  
  225.      tms5220_set_frequency -- adjusts the playback frequency
  226.  
  227. ***********************************************************************************************/
  228.  
  229. void tms5220_set_frequency(int frequency)
  230. {
  231.     /* skip if output frequency is zero */
  232.     if (!Machine->sample_rate)
  233.         return;
  234.  
  235.     /* update the stream and compute a new step size */
  236.     if (stream != -1)
  237.         stream_update(stream, 0);
  238.     source_step = (UINT32)((double)(frequency / 80) * (double)FRAC_ONE / (double)Machine->sample_rate);
  239. }
  240.